package com.xxl.job.admin.job;

import com.google.gson.Gson;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.ruoyi.backups.domain.MysqlBacklog;
import com.ruoyi.backups.domain.MysqlBackups;
import com.ruoyi.backups.domain.OosConfig;
import com.ruoyi.backups.service.IMysqlBacklogService;
import com.ruoyi.backups.service.IMysqlBackupsService;
import com.ruoyi.backups.service.impl.OosConfigServiceImpl;
import com.ruoyi.common.sdk.connection.MySqlConnectionClient;
import com.ruoyi.common.sdk.oos.AliyunOosClient;
import com.ruoyi.common.sdk.ssh.JschClient;
import com.ruoyi.common.utils.DateUtils;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.unit.DataUnit;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.Map;

/**
 * @author xiaoyan 远程数据文件备份任务
 * @date 2024/9/9 下午8:39
 **/
@Component
public class FileDataBackupJob {
    private final Logger log = LoggerFactory.getLogger(DemoJob.class);

    @Autowired
    private IMysqlBackupsService mysqlBackupsService;

    @Autowired
    private OosConfigServiceImpl oosConfigService;

    @Autowired
    private IMysqlBacklogService mysqlBacklogService;


    @XxlJob("fileDataBackupJob")
    public void fileDataBackupJobHandler() {
        String jobParam = XxlJobHelper.getJobParam();
        // 创建Gson实例
        Gson gson = new Gson();
        Map<String, String> params = gson.fromJson(jobParam, Map.class);
        Long oosId = Long.valueOf(params.get("oosId"));
        Long dataId = Long.valueOf(params.get("dataId"));
        String path = String.valueOf(params.get("path"));

        if (oosId == null) {
            log.info("OOSID is null：请重新输入！");
            return;
        }
        if (dataId == null) {
            log.info("DATAID is null：请重新输入！");
            return;
        }
        //查找数据源
        MysqlBackups mysqlBackups = mysqlBackupsService.selectMysqlBackupsById(dataId);
        if (mysqlBackups == null) {
            log.info("mysqlBackups is null 请输入正确的DATAID!");
            return;
        }
        OosConfig oosConfig = oosConfigService.selectOosConfigById(oosId);
        if (oosConfig == null) {
            log.info("oosConfig is null 请输入正确的OOSID！");
            return;
        }
        //构建连接
        log.info("----------Begin：导出文件中----------");

        JschClient jschClient = new JschClient.Builder()
                .ip(mysqlBackups.getMysqlIp())
                .port(mysqlBackups.getSshPort())
                .username(mysqlBackups.getSshUsername())
                .password(mysqlBackups.getSshPassword()).build();

        Session jSchSession = jschClient.getJSchSession();

        String filePath = "./Filetmp/" + DateUtils.getTime().replace(" ","").replace("-","").replace(":","")+"/";
        //缓存文件路径
        File filetmp = new File(filePath+new File(path).getName());
        filetmp.mkdir();

        //zip缓存路径
        String zipPath="./Filezip/" + DateUtils.getTime().replace(" ","").replace("-","").replace(":","")+"/";
        File zipfile = new File(zipPath+new File(path).getName()+".zip");
        zipfile.mkdir();


        try {
            jschClient.downloadAndZipRemoteDirectory(jSchSession, path, filetmp.getPath(), zipfile.getPath());
        } catch (JSchException e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        } catch (SftpException e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        }


        //上传到OOS
        AliyunOosClient aliyunOosClient = new AliyunOosClient.Builder()
                .accessKeyId(oosConfig.getAccessKey())
                .bucketName(oosConfig.getBucketName())
                .endpoint(oosConfig.getEndpoint())
                .accessKeySecret(oosConfig.getAccessSecret()).build();



        String name = zipfile.getName();
        log.info("----------上传阿里云----------");
        aliyunOosClient.uploadFileToOSS(zipfile.getPath(),mysqlBackups.getMysqlIp()+"/"+DateUtils.getDate()+"/"+name);
//        https://sql-bach.oss-cn-beijing.aliyuncs.com/scdl/scdl-20240909152744.sql
//        https://oss-cn-beijing.aliyuncs.com

        //插入日志
        String endpoint = oosConfig.getEndpoint();
        String url2 = endpoint.replace("https://", "");
        String bucketName = oosConfig.getBucketName();
        String url = "https://"+bucketName+"."+url2+"/"+mysqlBackups.getMysqlIp()+"/"+DateUtils.getDate()+"/"+name;

        MysqlBacklog mysqlBacklog=new MysqlBacklog();
        mysqlBacklog.setMysqlId(dataId.toString());
        mysqlBacklog.setOosId(oosId.toString());
        mysqlBacklog.setFileEndpoint(url);

        // 获取文件大小（以字节为单位）
        long fileSizeInBytes = zipfile.length();
        // 将字节转换为兆字节
        double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024);
        // 格式化输出结果，精确到小数点后两位
        DecimalFormat df = new DecimalFormat("#.00");
        String formattedSize = df.format(fileSizeInMB);
        mysqlBacklog.setFileSize(formattedSize+"MB");
        mysqlBacklog.setFilePath(zipfile.getPath());
        mysqlBacklogService.insertMysqlBacklog(mysqlBacklog);
        deleteAllFilesAndSubdirectories(new File(filePath));
        deleteAllFilesAndSubdirectories(new File(zipPath));
        log.info("----------任务执行完成----------");
    }
    /**
     * 删除给定目录下的所有文件和子目录
     *
     * @param directory 要清理的目录
     */
    private static void deleteAllFilesAndSubdirectories(File directory) {
        if (directory.exists() && directory.isDirectory()) {
            // 获取目录下的所有文件和子目录
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        // 如果是目录，递归删除
                        deleteAllFilesAndSubdirectories(file);
                    } else {
                        // 如果是文件，直接删除
                        if (!file.delete()) {
                            System.out.println("Failed to delete file: " + file.getAbsolutePath());
                        } else {
                            System.out.println("Deleted file: " + file.getAbsolutePath());
                        }
                    }
                }
            }
            // 尝试删除空目录
            if (!directory.delete()) {
                System.out.println("Failed to delete directory: " + directory.getAbsolutePath());
            } else {
                System.out.println("Deleted directory: " + directory.getAbsolutePath());
            }
        } else {
            System.out.println("The provided path does not exist or is not a directory: " + directory.getAbsolutePath());
        }
    }

}
